package root;

import javax.management.AttributeNotFoundException;

import root.loan.CurrentDate;
import root.message.MessageType;
import root.user.User;
import root.user.UserManager;
import exceptions.AbsentAtributException;
import exceptions.BorrowDoesNotExist;
import exceptions.CriterioInexistente;
import exceptions.CriterioInvalido;
import exceptions.FriendshipDoesNotExist;
import exceptions.HasAlreadyDoneException;
import exceptions.InexistentCategory;
import exceptions.InexistentCriterySortType;
import exceptions.InexistentSortType;
import exceptions.InexistentTopic;
import exceptions.InexistentType;
import exceptions.InvalidAtributException;
import exceptions.InvalidBorrowId;
import exceptions.InvalidCategory;
import exceptions.InvalidCriterySortType;
import exceptions.InvalidDurationException;
import exceptions.InvalidItemCategoryException;
import exceptions.InvalidItemNameException;
import exceptions.InvalidKeyException;
import exceptions.InvalidLogin;
import exceptions.InvalidMessage;
import exceptions.InvalidName;
import exceptions.InvalidReceiver;
import exceptions.InvalidSender;
import exceptions.InvalidSession;
import exceptions.InvalidSortType;
import exceptions.InvalidSubject;
import exceptions.InvalidTopic;
import exceptions.InvalidType;
import exceptions.InvalidUserAddress;
import exceptions.InvalidUserException;
import exceptions.InvalidUserName;
import exceptions.InvalidUserUsername;
import exceptions.IsNotOnwerException;
import exceptions.ItemDoesNotExist;
import exceptions.ItemHasAlreadyBorrowedException;
import exceptions.ItemRequestAlreadyExistsException;
import exceptions.LoanHasAlreadyBeenApprovedException;
import exceptions.PermissionDeniedException;
import exceptions.SessionDoesNotExist;
import exceptions.TipoOrdenacaoInexistente;
import exceptions.TipoOrdenacaoInvalido;
import exceptions.UserAlreadyExistsException;
import exceptions.UserNotExistsException;
import exceptions.WithoutPermissionRequestLoanException;
import exceptions.YouAreAlreadyFriends;
import exceptions.YouHaveAlreadyRequestedFriendship;
import exceptions.YouHaventReceivedARequest;

public class MainManager {
	
	private static MainManager mainManager;
	private UserManager userManager;
	private SessionManager sessionManager;
	private CurrentDate loanManager;
	
	private MainManager() {
		UserManager.setInstance(null);
		SessionManager.setInstance(null);
		CurrentDate.setInstance(null);
		userManager = UserManager.getUserManager();
		sessionManager = SessionManager.getSessionManager();
		loanManager = CurrentDate.getInstance();
	}
	
	public String pesquisarItem(String idSessao, String chave, String atributo, String tipoOrdenacao, String criterioOrdenacao) 
	throws InvalidSession, SessionDoesNotExist, UserNotExistsException, TipoOrdenacaoInexistente,
	TipoOrdenacaoInvalido, CriterioInvalido, CriterioInexistente, InvalidAtributException,
	ItemDoesNotExist, AbsentAtributException, InvalidKeyException, InvalidSortType, InexistentSortType, InexistentCriterySortType, InvalidCriterySortType {
		Session session = sessionManager.getSession(idSessao);
		User user = userManager.getUser( session.getLogin() );
		return user.getSearchItemsString(chave, atributo, tipoOrdenacao, criterioOrdenacao);
	}

	public String enviarMensagem(String idSessao, String destinatario,
			String assunto, String mensagem) throws InvalidSender, InvalidReceiver, UserNotExistsException, InvalidMessage, InvalidSubject, SessionDoesNotExist, InvalidSession {
		User sender,dest;
		try{
			Session session = sessionManager.getSession(idSessao);
			sender = userManager.getUser( session.getLogin() );
			dest = userManager.getUser( destinatario );
		}catch(UserNotExistsException e){
			if(e.getMessage().contains("inexistente")) throw new UserNotExistsException("Destinatário inexistente");
			throw new UserNotExistsException("Destinatário inválido");
		}
			return sender.createMessage(dest, assunto, mensagem, MessageType.OFF_TOPIC);
	}
	public String enviarMensagem(String idSessao, String destinatario,
			String assunto, String mensagem, String idRequisicaoEmprestimo) throws Exception {
		User sender,dest;
		try{
			Session session = sessionManager.getSession(idSessao);
			sender = userManager.getUser( session.getLogin() );
			dest = userManager.getUser( destinatario );
		}catch(UserNotExistsException e){
			if(e.getMessage().contains("inexistente")) throw new UserNotExistsException("Destinatário inexistente");
			throw new UserNotExistsException("Destinatário inválido");
		}
		return sender.createMessage(dest, assunto, mensagem, idRequisicaoEmprestimo);
	}
	
	public String lerTopicos(String idSessao, String tipo) throws
	SessionDoesNotExist, InvalidSession, UserNotExistsException, InvalidType, InexistentType {
		Session session = sessionManager.getSession(idSessao);
		String login = session.getLogin();
		User user = userManager.getUser(login);
		return user.getTopics(tipo);
	}
	
	public String getRanking(String idSessao, String categoria) throws SessionDoesNotExist, InvalidSession, UserNotExistsException, InvalidCategory, InexistentCategory {
		Session session = sessionManager.getSession(idSessao);
		String login = session.getLogin();
		User user = userManager.getUser(login);
		return userManager.getRanking(user, categoria);
	}
	
	public String lerMensagens(String idSessao, String idTopico) throws
	Exception {
		Session session = sessionManager.getSession(idSessao);
		String login = session.getLogin();
		User user = userManager.getUser(login);
		return userManager.getStringMessages(user,idTopico);			
		
	}
	
	public static void encerrarSistema() {
		zerarSistema();
	}
	public static void zerarSistema() {
		UserManager.setInstance(null);
		SessionManager.setInstance(null);
		CurrentDate.setInstance(null);
		getMainManager().userManager = UserManager.getUserManager();
		getMainManager().sessionManager = SessionManager.getSessionManager();
		getMainManager().loanManager = CurrentDate.getInstance();
	}

	public static MainManager getMainManager(){
		if(mainManager==null){
			mainManager= new MainManager();
		}
		return mainManager;
	}
	
	public String getRequisicoesDeAmizade(String idSessao) throws UserNotExistsException, SessionDoesNotExist, InvalidSession {
		Session session = sessionManager.getSession(idSessao);
		String login = session.getLogin();
		User request = userManager.getUser(login);
		return request.getFriendshipRequests();
	}
	public void criarUsuario(String username,
			String name,String address) throws InvalidUserUsername, InvalidUserName, InvalidUserAddress, UserAlreadyExistsException, InvalidUserException{
		userManager.createUser(username, name, address);
	}
	
	public String abrirSessao(String login) throws InvalidLogin, UserNotExistsException {
		return sessionManager.createSession(login);
	}
	
	public String getAtributoUsuario(String login,String atributo) throws InvalidUserUsername, UserNotExistsException, InvalidAtributException, AttributeNotFoundException{
		return userManager.getAttribute(login, atributo);
	}
	
	public String getAtributoItem(String idItem,String atributo) throws InvalidAtributException, AbsentAtributException, ItemDoesNotExist{
		return userManager.getAtributoItem(idItem, atributo);
	}
	
	public String localizarUsuario(String idSessao,String chave,String atributo) throws InvalidSession, InvalidAtributException, SessionDoesNotExist, InvalidKeyException, UserNotExistsException{
		return userManager.findUser(idSessao, chave, atributo);
	}
	
	public String localizarUsuario(String idSessao) throws InvalidSession, InvalidAtributException, SessionDoesNotExist, InvalidKeyException, UserNotExistsException{
		return userManager.findUser(idSessao);
	}
	
	public void requisitarAmizade(String idSessao, String loginAmigo) throws UserNotExistsException, SessionDoesNotExist, InvalidSession, YouHaveAlreadyRequestedFriendship, YouAreAlreadyFriends, InvalidUserException{
		Session session = sessionManager.getSession(idSessao);
		String login = session.getLogin();
		User request = userManager.getUser(login);
		User target = userManager.getUser(loginAmigo);
		request.requestFriendship(target);
	}
	
	public void aprovarAmizade(String idSessao,String loginAprovar) throws UserNotExistsException, SessionDoesNotExist, InvalidSession, YouHaveAlreadyRequestedFriendship, YouAreAlreadyFriends, InvalidUserException, YouHaventReceivedARequest{
		Session session = sessionManager.getSession(idSessao);
		String login = session.getLogin();
		User request = userManager.getUser(login);
		User target = userManager.getUser(loginAprovar);
		request.acceptFriendship(target);
	
	}
	
	public String ehAmigo(String idSessao,String loginUser) throws UserNotExistsException, SessionDoesNotExist, InvalidSession{
		Session session = sessionManager.getSession(idSessao);
		String login = session.getLogin();
		User request = userManager.getUser(login);
		User other = userManager.getUser(loginUser);
		return String.valueOf(request.isFriend(other));
	}
	
	public String getAmigos(String idSessao) throws UserNotExistsException, SessionDoesNotExist, InvalidSession{
		return userManager.getUser(sessionManager.getSession(idSessao).getLogin()).getFriendsStringMode();
	}
	
	public String getAmigos(String idSessao,String login) throws UserNotExistsException, SessionDoesNotExist, InvalidSession{
		return userManager.getUser(sessionManager.getSession(idSessao).getLogin()).getFriendsStringMode(userManager.getUser(login));
	}
	
	public String getItens(String idSessao) throws UserNotExistsException, SessionDoesNotExist, InvalidSession{
		return userManager.getUser(sessionManager.getSession(idSessao).getLogin()).getSelfItensDescription();
	}
	
	public String getItens(String idSessao,String login) throws UserNotExistsException, SessionDoesNotExist, InvalidSession, PermissionDeniedException{
		return userManager.getUser(sessionManager.getSession(idSessao).getLogin()).getFriendItensDescription(userManager.getUser(login));
	}
	
	public void desfazerAmizade(String idSessao, String amigo) throws SessionDoesNotExist, InvalidSession, UserNotExistsException, FriendshipDoesNotExist {
		Session session = sessionManager.getSession(idSessao);
		String login = session.getLogin();
		User requester = userManager.getUser(login);
		User target = userManager.getUser(amigo);
		requester.eraseFriendship(target);
	}
	
	public String getEmprestimos(String idSessao,String tipo) throws InvalidAtributException, AbsentAtributException, ItemDoesNotExist, UserNotExistsException, SessionDoesNotExist, InvalidSession{
		Session session = sessionManager.getSession(idSessao);
		String login = session.getLogin();
		return userManager.getUser(login).getEmprestimos(tipo);
	}
	
	public String requisitarEmprestimo(String idSessao,String idItem,int duracao) throws 
	SessionDoesNotExist, InvalidSession, ItemDoesNotExist, ItemRequestAlreadyExistsException, 
	WithoutPermissionRequestLoanException, UserNotExistsException, InvalidDurationException,
	InvalidSubject, InvalidReceiver, InvalidMessage, InvalidSender, InvalidAtributException,
	AbsentAtributException, IsNotOnwerException{
		Session session = sessionManager.getSession(idSessao);
		String login = session.getLogin();
		return userManager.requisitarEmprestimo(userManager.getUser(login),idItem, duracao);
	}
	
	public String aprovarEmprestimo(String idSessao, String idRequisicaoEmprestimo) throws IsNotOnwerException, BorrowDoesNotExist, ItemDoesNotExist, LoanHasAlreadyBeenApprovedException, ItemHasAlreadyBorrowedException, UserNotExistsException, SessionDoesNotExist, InvalidSession, InvalidBorrowId, PermissionDeniedException{
		Session session = sessionManager.getSession(idSessao);
		String login = session.getLogin();
		return userManager.getUser(login).approveLoan(idRequisicaoEmprestimo);
	}
	
	public void devolverItem(String idSessao, String idEmprestimo) throws SessionDoesNotExist, InvalidSession, BorrowDoesNotExist, PermissionDeniedException, HasAlreadyDoneException, UserNotExistsException, InvalidBorrowId{
		Session session = sessionManager.getSession(idSessao);
		String login = session.getLogin();
		userManager.returnItem(userManager.getUser(login),idEmprestimo);
	}
	
	public void apagarItem(String idsessao, String iditem) throws ItemDoesNotExist, IsNotOnwerException, UserNotExistsException, SessionDoesNotExist, InvalidSession, PermissionDeniedException{
		userManager.deleteItem(userManager.getUser(sessionManager.getSession(idsessao).getLogin()),iditem);

	}
	
	public String publicarPedido(String idSessao, String nomeItem, String descricaoItem) throws UserNotExistsException, SessionDoesNotExist, InvalidSession, InvalidAtributException{
		User user = userManager.getUser(sessionManager.getSession(idSessao).getLogin());
		return user.publicarPedido(nomeItem, descricaoItem);
		
	}
	
	public void rePublicarPedido(String idSessao, String idPedido) throws UserNotExistsException, SessionDoesNotExist, InvalidSession, InvalidAtributException{
		User user = userManager.getUser(sessionManager.getSession(idSessao).getLogin());
		user.rePublicarPedido(idPedido);
		
	}
	
	public void oferecerItem(String idSessao, String idPedido, String itemId) throws UserNotExistsException, SessionDoesNotExist, InvalidSession, InvalidAtributException, ItemDoesNotExist, InvalidSender, InvalidReceiver, InvalidMessage, InvalidSubject{
		User user = userManager.getUser(sessionManager.getSession(idSessao).getLogin());
		userManager.oferecerItem(user,idPedido,itemId);
		
	}
	
	public void requisitarDevolucao(String idSessao, String idEmprestimo ) throws BorrowDoesNotExist, InvalidBorrowId, HasAlreadyDoneException, PermissionDeniedException, UserNotExistsException, SessionDoesNotExist, InvalidSession, ItemDoesNotExist, InvalidAtributException, AbsentAtributException, InvalidMessage, InvalidSubject, InvalidReceiver{
		Session session = sessionManager.getSession(idSessao);
		String login = session.getLogin();
		userManager.requestDevolution(userManager.getUser(login),idEmprestimo);
	}
	
	public void adicionarDias(int dias){
		loanManager.addDays(dias);
	}
	
	public void confirmarTerminoEmprestimo(String idSessao, String idEmprestimo) throws SessionDoesNotExist, InvalidSession, BorrowDoesNotExist, PermissionDeniedException, HasAlreadyDoneException, ItemDoesNotExist, UserNotExistsException, InvalidBorrowId {
		Session session = sessionManager.getSession(idSessao);
		String login = session.getLogin();
		userManager.completeLoan(userManager.getUser(login), idEmprestimo);
	}
	
	public void registrarInteresse(String idSessao, String idItem) throws PermissionDeniedException, HasAlreadyDoneException, ItemDoesNotExist, InvalidBorrowId, BorrowDoesNotExist, UserNotExistsException, SessionDoesNotExist, InvalidSession, InvalidAtributException{
		Session session = sessionManager.getSession(idSessao);
		String login = session.getLogin();
		userManager.addItemInterest(userManager.getUser(login),idItem);
	}
	
	public Session getSession(String id) throws SessionDoesNotExist, InvalidSession {
		return sessionManager.getSession(id);
	}

	public String cadastrarItem(String sessionId, String name,
			String description, String category) throws InvalidName, InvalidCategory, SessionDoesNotExist, InvalidItemNameException, InvalidItemCategoryException, UserNotExistsException, InvalidSession {
		Session session = sessionManager.getSession(sessionId);
		String login = session.getLogin();
		return userManager.getUser(sessionManager.getSession(sessionId).getLogin()).addItem(userManager.getUser(login), name, description, category);

	}
	
	public String historicoAtividades(String idSessao) throws UserNotExistsException, SessionDoesNotExist, InvalidSession{
		return userManager.getUser(sessionManager.getSession(idSessao).getLogin()).getHistorico();
	}
	public String historicoAtividadesConjunto(String idSessao) throws SessionDoesNotExist, InvalidSession, UserNotExistsException{
		Session session = sessionManager.getSession(idSessao);
		String login = session.getLogin();
		User user = userManager.getUser(login);
		return user.getHistoricoAtividadesConjunto();
	}
	
}
